/* 
 * Die Klasse stellt den Mitarbeitern der Bibliothek einen Editor zur
 * Verfuegung mit dem sie die Regalstandorte visuell darstellen koennen.
 * 
 * Datei: Editor.java         Autor:  Christian Plappert
 * Datum: 20.12.2011          Version: 0.6.1
 * 
 * Historie: 
 * 
 * 20.12.2011:  v0.6.1  Es kann nur noch eine Instanz des Editors 
 *                      gleichzeitig laufen.
 * 12.12.2011:	v0.6	Schliessen-Verhalten festgelegt, sodass nicht 
 * 			mehr das gesamte Projekt geschlossen wird beim 
 * 			Beenden.
 * 			Kollisionserkennung funktioniert auch beim 
 * 			Drehen von Objekten
 * 09.12.2011:	v0.5.5	Kollisionserkennung integriert.
 * 08.12.2011:	v0.5	Integration der Medienverwaltung, 
 * 			Klasse Eingabemaske geloescht
 * 04.12.2011:  v0.4.5  Regale koennen nicht mehr ausserhalb der 
 * 			Bibliothek gezeichnet werden.
 * 20.11.2011:  v0.4    Regale koennen verschoben, bearbeitet und 
 *                      geloescht werden.
 * 18.11.2011:  v0.3.5  ausfuehrliches Refactoring
 * 17.11.2011:  v0.3.0  Regale koennen gezeichnet werden.
 * 16.11.2011:  v0.2.5  MouseListener implementiert.
 * 12.11.2011:  v0.2    Klasse macht Gebrauch von Eingabemaske.
 * 09.11.2011:  v0.1.1  EventListener wurden ergaenzt.
 * 08.11.2011:  v0.1    Klasse wurde angelegt und einige wichtige 
 *                      GUI-Elemente integriert. 
 *                      
 */
package bibvis;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionAdapter;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.regex.Pattern;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.UIManager;

import kommunikation.UngueltigeEingabeAusnahme;
import kommunikation.Parser.NichtImAlphabetAusnahme;
import medienverwaltung.Regal;
import medienverwaltung.Standort;
import medienverwaltung.Standortverwalter;
import basis.lokal.Lokalisierung;

public class Editor extends JFrame
{
  private static final long serialVersionUID = 3052927423329056629L;

  /* primitive Daten-Felder */
  private boolean eintritt = false, bearbeitet = false, einmal = true;
  private Point koordinateMaus;
  /* Zugriff von Markierer */
  private Color regalFarbe, tuerFarbe, fensterFarbe, thekenFarbe,
      markierungsFarbe, layoutFarbe;

  /*
   * Zwischenraum legt den Abstand der Objekte (Regale, Tueren, Fenster)
   * auf der Zeicheflaeche fest
   */
  private static int MASSSTAB = 5, ZWISCHENRAUM = 5;
  private int altX, altY;
  private String sprache;

  /* GUI-Felder */
  private JButton buttonR, buttonT, buttonF, buttonTh;
  private JLabel standortBezText, standortMasText;
  private JPanel titelLeiste, pufferzone;
  private JTextPane standortBezeichner, standortMasse;
  private JMenuItem menuItem1, menuItem2, menuItem3, menuItem4,
      menuItem5, menuItem6, menuItem7, menuItem8, menuItem9,
      menuItem11, menuItem12, menuItem13;

  /*
   * menuD = Menueeintrag Datei, menuB = Menueeintrag Bearbeiten, menuA
   * = Menueeintrag Ansicht
   */
  private JMenu menuD, menuB, menuA;
  private JMenuBar menuBar;

  /* Klassen-Felder */
  private Zeichenblatt zeichenblatt;
  private Datenbank db;
  private StandortAnlegenPanel sap;
  private RegalAnlegenPanel rap;
  private ObjektAnlegenPanel oap;
  private Lokalisierung lokal;
  private ObjektAufzaehlung typ;
  private StandortDaten std;
  /*
   * Datenfeld, das ein bestimmtes Rechteck enthaelt, welches vom
   * Benutzer selektiert wurde.
   */
  private FigurZustand markiertesRechteck;
  private ButtonDeaktiviertListener budl;


  public Editor (String sprache)
  {
    final String STANDARD_TITEL = "BibVis-Editor";
    final int STANDARD_FENSTER_BREITE = 640;
    final int STANDARD_FENSTER_HOEHE = 480;

    setTitle (STANDARD_TITEL);
    setSize (STANDARD_FENSTER_BREITE, STANDARD_FENSTER_HOEHE);
    setLocationRelativeTo (null);

    /* Standardverhalten festlegen, wenn Fenster geschlossen wird */
    addWindowListener (new FensterListener ());

    this.sprache = sprache;

    /* erzeuge das Fenster */
    erzeugeFenster (sprache);

    /* zeige das Fenster nicht an */
    setVisible (false);
  }


  /**
   * Aktiviert den Editor.
   * 
   * @see FassadeBibVis#legeBibVisAn()
   */
  protected void start()
  {
    /* zeige das Fenster an */
    setVisible (true);
  }


  /**
   * Erzeugt das Editorfenster. Unter anderem werden hier Menueleiste
   * mit entsprechenden Eintraegen initialisiert und angeordnet.
   */
  private void erzeugeFenster(String sprache)
  {
    zeichenblatt = new Zeichenblatt ();
    pufferzone = new JPanel ();

    db = new Datenbank ();
    std = new StandortDaten ();
    menuBar = new JMenuBar ();

    db.setzeSprachwahl (new Sprachwahl (sprache));
    lokal = db.gibSprachwahl ().lokal;

    regalFarbe = Color.green;
    tuerFarbe = Color.yellow;
    fensterFarbe = Color.LIGHT_GRAY;
    markierungsFarbe = Color.red;
    thekenFarbe = Color.cyan;

    zeichenblatt.addMouseMotionListener (new VerschiebeListener ());
    zeichenblatt.addMouseListener (new KollisionsListener ());

    try
    {
      UIManager.setLookAndFeel (UIManager
	.getCrossPlatformLookAndFeelClassName ());
    }
    catch (Exception e)
    {
      e.getStackTrace ();
    }

    layoutFarbe = new Color (154, 165, 127);
    menuBar.setOpaque (true);
    menuBar.setBackground (layoutFarbe);

    /*
     * Menue-Eintraege initialisieren.
     */
    menuD = new JMenu (lokal.gibUebersetzung ("Datei"));
    menuBar.add (menuD);

    menuItem1 = new JMenuItem (
      lokal.gibUebersetzung ("Neue Bibliothek anlegen"),
      KeyEvent.VK_N);
    menuItem1.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_N,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem1);
    menuItem1.addActionListener (new DateiNeueBibAnlegenListener ());

    menuItem2 = new JMenuItem (
      lokal.gibUebersetzung ("Bibliothek laden"), KeyEvent.VK_L);
    menuItem2.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_L,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem2);
    menuItem2.addActionListener (new DateiBibLadenListener ());

    menuItem3 = new JMenuItem (
      lokal.gibUebersetzung ("Bibliothek speichern"), KeyEvent.VK_S);
    menuItem3.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_S,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem3);
    menuItem3.setEnabled (false);
    menuItem3.addActionListener (new DateiBibSpeichernListener ());

    menuItem12 = new JMenuItem (
      lokal.gibUebersetzung ("Bibliothek speichern unter..."),
      KeyEvent.VK_U);
    menuItem12.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_U,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem12);
    menuItem12.setEnabled (false);
    menuItem12
      .addActionListener (new DateiBibSpeichernUnterListener ());

    menuD.addSeparator ();

    menuItem13 = new JMenuItem (
      lokal.gibUebersetzung ("Bibliothek loeschen"), KeyEvent.VK_D);
    menuItem13.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_D,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem13);
    menuItem13.addActionListener (new DateiBibLoeschenListener ());

    menuD.addSeparator ();

    menuItem4 = new JMenuItem (lokal.gibUebersetzung ("Schliessen"),
      KeyEvent.VK_Q);
    menuItem4.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_Q,
      ActionEvent.CTRL_MASK));
    menuD.add (menuItem4);
    menuItem4.addActionListener (new DateiSchliessenListener ());

    /*
     * Zunaechst unsichtbare Menue-Eintraege
     */
    menuB = new JMenu (lokal.gibUebersetzung ("Bearbeiten"));
    menuBar.add (menuB);

    menuItem5 = new JMenuItem (
      lokal.gibUebersetzung ("Standort aendern"), KeyEvent.VK_A);
    menuItem5.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_A,
      ActionEvent.CTRL_MASK));
    menuItem5
      .addActionListener (new BearbeitenStandortAendernListener ());
    menuB.add (menuItem5);

    menuB.addSeparator ();

    menuItem6 = new JMenuItem (
      lokal.gibUebersetzung ("Objekt loeschen"), KeyEvent.VK_R);
    menuItem6.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_R,
      ActionEvent.CTRL_MASK));
    menuItem6.addActionListener (new BearbeitenLoeschenListener ());
    menuB.add (menuItem6);

    menuItem7 = new JMenuItem (
      lokal.gibUebersetzung ("Objekt bearbeiten"), KeyEvent.VK_E);
    menuItem7.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_E,
      ActionEvent.CTRL_MASK));
    menuItem7.addActionListener (new BearbeitenBearbeitenListener ());
    menuB.add (menuItem7);

    menuItem8 = new JMenuItem (lokal.gibUebersetzung ("Objekt drehen"),
      KeyEvent.VK_T);
    menuItem8.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_T,
      ActionEvent.CTRL_MASK));
    menuItem8.addActionListener (new BearbeitenRegalDrehenListener ());
    menuB.add (menuItem8);

    menuB.addSeparator ();

    menuItem9 = new JMenuItem (lokal.gibUebersetzung ("Faerben"),
      KeyEvent.VK_F);
    menuItem9.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_5,
      ActionEvent.ALT_MASK));
    menuItem9.addActionListener (new BearbeitenFaerbenListener ());
    menuB.add (menuItem9);

    // menuB.addSeparator ();

    // menuItem10 = new JMenuItem (
    // lokal.gibUebersetzung ("Listen ausgeben"), KeyEvent.VK_P);
    // menuItem10.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_P,
    // ActionEvent.CTRL_MASK));
    // menuItem10
    // .addActionListener (new BearbeitenListenAusgebenListener ());
    // menuB.add (menuItem10);

    menuB.setVisible (false);

    menuA = new JMenu (lokal.gibUebersetzung ("Ansicht"));
    menuBar.add (menuA);

    menuItem11 = new JMenuItem (
      lokal.gibUebersetzung ("Sprache waehlen"), KeyEvent.VK_C);
    menuItem11.setAccelerator (KeyStroke.getKeyStroke (KeyEvent.VK_C,
      ActionEvent.CTRL_MASK));
    menuItem11.addActionListener (new AnsichtSpracheWaehlenListener ());
    menuA.add (menuItem11);

    /*
     * Initialisiere Menue-Leiste.
     */
    setJMenuBar (menuBar);

    /*
     * Initialisiere Layout.
     */
    standortBezText = new JLabel ();
    standortBezText.setText (lokal.gibUebersetzung ("Standort: "));
    standortMasText = new JLabel ();
    standortMasText.setText (lokal.gibUebersetzung ("Masse: "));
    standortMasse = new JTextPane ();
    standortMasse.setText (lokal.gibUebersetzung ("--leer--"));
    standortBezeichner = new JTextPane ();
    standortBezeichner.setText (lokal.gibUebersetzung ("--leer--"));
    standortBezeichner.setEditable (false);
    standortBezText.setLabelFor (standortBezeichner);
    titelLeiste = new JPanel ();
    titelLeiste.setBorder (BorderFactory.createRaisedBevelBorder ());
    titelLeiste.add (standortBezText);
    titelLeiste.add (standortBezeichner);
    titelLeiste.add (standortMasText);
    titelLeiste.add (standortMasse);
    getContentPane ().add (titelLeiste, BorderLayout.PAGE_START);

    /*
     * Der MouseListener "ZeichenblattListener" setzt ein Flag, ob sich
     * der Mauszeiger auf der Zeichenflaeche befindet oder nicht.
     */
    zeichenblatt.addMouseListener (new ZeichenblattListener ());

    pufferzone.setPreferredSize (new Dimension (800 + 20, 600 + 20));
    zeichenblatt.setPreferredSize (new Dimension (800, 600));
    pufferzone.setOpaque (true);
    pufferzone.setBackground (layoutFarbe);
    pufferzone.add (zeichenblatt, BorderLayout.CENTER);
    getContentPane ().add (pufferzone, BorderLayout.CENTER);

    initialisiereSchaltflaechen ();

    /*
     * Zeige Fenster an.
     */
    setResizable (false);
    pack ();
    setVisible (true);
  }


  /**
   * Gestaltet das Editorfenster mit Zeichenflaeche und Schaltflaechen.
   * Dabei wird der Massstab entsprechend der eingegebenen Ausmasse so
   * angepasst, dass die gewuenschte Fenstergroesse eingehalten wird.
   * 
   * @param standort
   *          : Die Zeichenkette des Standorts
   * @param laenge
   *          : Die Laenge des Raums
   * @param breite
   *          : Die Breite des Raums
   */
  private void setzeEditorFenster(String standort, int laenge,
    int breite)
  {
    int max;
    /* max. 800 * 600 */
    max = -1;
    if ( ( (laenge * MASSSTAB) > 800) || ( (breite * MASSSTAB) > 800))
    {
      while ( ( (laenge * MASSSTAB) > 800)
	|| ( (breite * MASSSTAB) > 800))
      {
	max = MASSSTAB;
	if (MASSSTAB == 0)
	{
	  MASSSTAB = 1;
	  while ( ( (laenge * MASSSTAB) > 800)
	    || ( (breite * MASSSTAB) > 800))
	  {
	    max = MASSSTAB;
	    MASSSTAB = MASSSTAB * (1 / 2);
	  }
	  break;
	}
	MASSSTAB--;
      }
    }
    if ((((laenge * MASSSTAB) < 800) || ((breite * MASSSTAB) < 800))
      && (max == -1))
    {
      while ((((laenge * MASSSTAB) < 800) || 
	((breite * MASSSTAB) < 800)))
      {
	max = MASSSTAB;
	MASSSTAB++;
      }
    }
    MASSSTAB = max;
    setSize (new Dimension (laenge * MASSSTAB, breite * MASSSTAB));

    pufferzone.setPreferredSize (new Dimension (
      (laenge * MASSSTAB) + 20, (breite * MASSSTAB) + 20));
    zeichenblatt.setPreferredSize (new Dimension (laenge * MASSSTAB,
      breite * MASSSTAB));

    standortBezeichner.setText (standort);
    standortMasse.setText (laenge + "x" + breite);

    getContentPane ().add (titelLeiste, BorderLayout.PAGE_START);

    menuB.setVisible (true);

    pack ();
    setzeFensterPositionX ();
  }


  /**
   * Die Schaltflechen werden erzeugt, erfuellen aber zunaechst noch
   * keine Funktion und werden daher deaktiviert und mit einem
   * entsprechenden "Listener" versehen, der den Nutzer informiert.
   */
  private void initialisiereSchaltflaechen()
  {
    JPanel links;
    budl = new ButtonDeaktiviertListener ();
    links = new JPanel ();
    links.setLayout (new GridLayout (6, 1));

    buttonR = new JButton (
      db.gibSprachwahl ().lokal.gibUebersetzung ("Regal hinzufuegen"));
    buttonR.setBackground (regalFarbe);
    buttonR.addMouseListener (budl);
    buttonR.setEnabled (false);
    links.add (buttonR);

    buttonT = new JButton (
      db.gibSprachwahl ().lokal.gibUebersetzung ("Tuer hinzufuegen"));
    buttonT.setBackground (tuerFarbe);
    buttonT.addMouseListener (budl);
    buttonT.setEnabled (false);
    links.add (buttonT);

    buttonF = new JButton (
      db.gibSprachwahl ().lokal
	.gibUebersetzung ("Fenster hinzufuegen"));
    buttonF.setBackground (fensterFarbe);
    buttonF.addMouseListener (budl);
    buttonF.setEnabled (false);
    links.add (buttonF);

    buttonTh = new JButton (
      db.gibSprachwahl ().lokal.gibUebersetzung ("Theke hinzufuegen"));
    buttonTh.setBackground (thekenFarbe);
    buttonTh.addMouseListener (budl);
    buttonTh.setEnabled (false);
    links.add (buttonTh);

    links.setBorder (BorderFactory.createRaisedBevelBorder ());

    getContentPane ().add (links, BorderLayout.LINE_START);
  }


  /**
   * Die deaktivierten Schaltflaechen werden aktiviert und ihre alten
   * Listener, die Nicht-Aktiviert-Ausnahmen erzeugten, durch neue
   * ersetzt, die nun die Funktion der Schaltflaechen implementieren.
   */
  private void aktiviereSchaltflaechen()
  {
    buttonR.setEnabled (true);
    buttonR.removeMouseListener (budl);
    buttonR
      .addMouseListener (new ButtonObjektHinzufuegenListener (null));
    buttonF.setEnabled (true);
    buttonF.removeMouseListener (budl);
    buttonF.addMouseListener (new ButtonObjektHinzufuegenListener (
      ObjektAufzaehlung.FENSTER));
    buttonT.setEnabled (true);
    buttonT.removeMouseListener (budl);
    buttonT.addMouseListener (new ButtonObjektHinzufuegenListener (
      ObjektAufzaehlung.TUER));
    buttonTh.setEnabled (true);
    buttonTh.removeMouseListener (budl);
    buttonTh.addMouseListener (new ButtonObjektHinzufuegenListener (
      ObjektAufzaehlung.THEKE));
    menuItem12.setEnabled (true);
    /* Unterstuetze Garbage Collection */
    budl = null;
  }


  /**
   * Eine neue Bibliothek wird angelegt. Alle temporaeren Listen der
   * Datenbank werden geloescht und neue erzeugt. Weiterhin werden
   * Voreintragungen in das Formular getaetigt.
   */
  private void neueBibAnlegen()
  {
    int groesse;
    Standort st;

    std = new StandortDaten ();

    sap = new StandortAnlegenPanel (db.gibSprachwahl ().lokal);
    sap.setLocationRelativeTo (this);
    sap.gibOk ().addActionListener (new SapBuOkListener ());
    sap.gibCa ().addActionListener (new SapBuCaListener ());

    // db.alleTemporaerenListenLoeschen ();

    /*
     * Die Zeichenkette "neueBib" ist ein Code, der bei der
     * Lokalisierung in einen Info-Text uebersetzt wird.
     */
    sap.gibTxt_info ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("neueBib"));

    /*
     * Pruefe, ob schon Standorte vorhanden sind. ja: Nimm als
     * voreingetragene Daten, die des letzten Standortes. nein: Trage
     * Standard-Werte ein.
     */
    if (! (db.gibStandort ().gibStandortListe ().isEmpty ()))
    {
      groesse = db.gibStandort ().gibStandortListe ().size () - 1;
      st = db.gibStandort ().gibStandortListe ().get (groesse);
      sap.setzeVoreingetrageneDaten (st.gibName (), st.gibOrt (),
	st.gibPlz (), st.gibHausnummer (), st.gibStrasse (),
	st.gibLaenge (), st.gibBreite ());
    }
    else
    {
      sap.setzeVoreingetrageneDaten ("Marquardstrasse", "Fulda",
	"36039", "35", "Marquardstrasse", 123, 123);
    }

    /* Deaktiviere Hintergrundfenster solange sap offen ist. */
    this.setEnabled (false);
  }


  /**
   * Mit Hilfe dieser Methode koennen saemtliche Daten eines Standorts
   * geaendert werden. Dabei werden die Daten des aktuellen Standorts
   * als Voreintragungen gespeichert.
   */
  private void standortAendern()
  {
    int id;
    Standort temp;

    sap = new StandortAnlegenPanel (db.gibSprachwahl ().lokal);
    sap.gibOk ().addActionListener (new SapAendernBuOkListener ());
    sap.gibCa ().addActionListener (new SapBuCaListener ());

    sap.gibTxt_info ().setText (lokal.gibUebersetzung 
      ("Die aktuelle Standortbezeichnung lautet: ")
	  + standortBezeichner.getText ()
	  + (lokal.gibUebersetzung 
	  ("\nBitte geben Sie den neuen Standort, sowie Dimensionen " +
	  "der Bibliothek ein.")));

    /*
     * Hole aktuellen Standort und setze dessen Daten als Voreintragung
     */
    id = std.gibZuordnungSI ().get (standortBezeichner.getText ());
    temp = db.gibStandort ().gibStandortTemp (id);
    sap.setzeVoreingetrageneDaten (temp.gibName (), temp.gibOrt (),
      temp.gibPlz (), temp.gibHausnummer (), temp.gibStrasse (),
      temp.gibLaenge (), temp.gibBreite ());
  }


  /**
   * Die Daten des Regals werden eingelesen und Daten in das Formular
   * voreingetragen.
   */
  private void regalHinzufuegenButton()
  {
    Regal letztes;

    rap = new RegalAnlegenPanel (db.gibSprachwahl ().lokal);
    rap.setLocationRelativeTo (this);
    /*
     * Die Zeichenkette "neuesRegal" ist ein Code, der bei der
     * Lokalisierung in einen Info-Text uebersetzt wird.
     */
    rap.getTxt_info ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("neuesRegal"));
    rap.getOk ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("ok"));
    rap.getCa ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("ca"));

    /*
     * voreingetragene Eingaben: Fall 1: Bereits Regale erstellt ->
     * letzte Eigenschaften anzeigen Fall 2: Keine Regale erstellt ->
     * Standard-Eigenschaften anzeigen
     */
    if (! (std.gibRegalListe ().isEmpty ()))
    {
      /* Hole Daten des zuletzt eingefuegten Regals */
      letztes = std.gibRegalListe ().get (
	std.gibRegalListe ().size () - 1);

      rap.setzeVoreingetrageneDaten (letztes.gibLaenge (),
	letztes.gibBreite (), letztes.gibEtagenHoehe (),
	letztes.gibAnzahlEtagen (), letztes.gibAbschnitte (),
	letztes.gibKuerzel ());
    }
    else
    {
      rap
	.setzeVoreingetrageneDaten (50, 10, 10, 10, 10, "Erstes Regal");
    }
    rap.getOk ().addActionListener (new RapBuOkListener ());
    rap.getCa ().addActionListener (new RapBuCaListener ());

    /* Deaktiviere Hintergrundfenster solange rap offen ist. */
    this.setEnabled (false);
  }


  /**
   * Die Daten des Objekts werden eingelesen.
   */
  private void objektHinzufuegenButton(ObjektAufzaehlung art)
  {
    oap = new ObjektAnlegenPanel (db.gibSprachwahl ().lokal, art);
    oap.setLocationRelativeTo (this);
    oap.gibOk ().addActionListener (new OapBuOkListener (art));
    oap.gibCa ().addActionListener (new OapBuCaListener ());

    oap.gibTxt_info ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung (art.name ()));
    oap.gibOk ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("ok"));
    oap.gibCa ().setText (
      db.gibSprachwahl ().lokal.gibUebersetzung ("ca"));

    /* Deaktiviere Hintergrundfenster solange oap offen ist. */
    this.setEnabled (false);
  }


  /**
   * Beschreibung: Loescht das markierte Regal aus allen temporaeren
   * Listen.
   * 
   * @param regal
   */
  private void regalLoeschen(Regal regal)
  {
    FigurZustand r;
    String[] optionen;
    int auswahl, id;

    for (int i = 0; i < std.gibRechteckListe ().size (); i++)
    {
      r = std.gibRechteckListe ().get (i);
      if (r == markiertesRechteck)
      {
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");

	auswahl = JOptionPane.showOptionDialog (
	  null,
	  lokal.gibUebersetzung ("Moechten Sie das Regal \"")
	    + std.gibZuordnungZR ().get (r).gibKuerzel ()
	    + lokal.gibUebersetzung ("\" loeschen?"),
	  lokal.gibUebersetzung ("Achtung!"),
	  JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
	  null, optionen, null);

	switch (auswahl)
	{
	  case 0:
	    std.ausAllenListenLoeschen (regal);

	    /* externe Schnittstelle */

	    id = std.gibZuordnungSI ()
	      .get (standortBezeichner.getText ());
	    db.gibStandort ().gibStandortTemp (id)
	      .regalEntfernen (regal.gibRegalId ());

	    /* Unterstuetze die Java Garbage Collection */
	    markiertesRechteck = null;

	    /* Fenster ueberprueft Komponenten */
	    repaint ();
	    break;

	  default:
	    ; /* tue nichts */
	}
      }
    }
  }


  private void objektLoeschen(FigurZustand objekt)
  {
    FigurZustand r;
    String[] optionen;
    int auswahl;

    for (int i = 0; i < std.gibZustandsListeObjekt ().size (); i++)
    {
      r = std.gibZustandsListeObjekt ().get (i);
      if (r == objekt)
      {
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");

	auswahl = JOptionPane.showOptionDialog (null,
	  lokal.gibUebersetzung ("Moechten Sie das markierte " +
	  "Objekt loeschen?"), lokal.gibUebersetzung ("Achtung!"),
	  JOptionPane.YES_NO_OPTION,
	  JOptionPane.QUESTION_MESSAGE, null, optionen, null);

	switch (auswahl)
	{
	  case 0:

	    std.gibObjektListe ().get (typ).remove (r);

	    /* Unterstuetze die Java Garbage Collection */
	    markiertesRechteck = null;
	    /* Fenster ueberprueft Komponenten */
	    repaint ();
	    break;

	  default:
	    ; /* tue nichts */
	}
      }
    }
  }


  /**
   * Das markierte Regal kann bearbeitet werden.
   * 
   * @param regal
   *          : Das markierte Regal
   */
  private void regalBearbeiten(Regal regal)
  {
    Regal t;

    rap = new RegalAnlegenPanel (db.gibSprachwahl ().lokal);
    rap.setLocationRelativeTo (this);
    rap.getOk ().addActionListener (new RapBuOkListener ());
    rap.getCa ().addActionListener (new RapBuCaListener ());
    t = regal;
    /* bearbeitet gibt an, dass der Aufruf von regalBearbeiten kommt */
    setzeBearbeitet (true);
    markiertesRechteck = std.gibZuordnungRZ ().get (regal);

    /*
     * Die Zeichenkette "neuesRegal" ist ein Code, der bei der
     * Lokalisierung in einen Info-Text uebersetzt wird.
     */
    rap.getTxt_info ().setText ("neuesRegal");

    rap.setzeVoreingetrageneDaten (t.gibLaenge (), t.gibBreite (),
      t.gibEtagenHoehe (), t.gibAnzahlEtagen (), t.gibAbschnitte (),
      t.gibKuerzel ());

    /* Deaktiviere Hintergrundfenster solange sap offen ist. */
    this.setEnabled (false);
  }


  /**
   * Das markierte Objekt kann bearbeitet werden bzgl. Laenge und
   * Breite.
   * 
   * @param objekt
   *          : Das markierte Objekt
   */
  private void objektBearbeiten(FigurZustand objekt, String art)
  {
    FigurZustand t;

    if (art.equals ("TUER"))
    {
      oap = new ObjektAnlegenPanel (db.gibSprachwahl ().lokal,
	ObjektAufzaehlung.TUER);
    }
    if (art.equals ("FENSTER"))
    {
      oap = new ObjektAnlegenPanel (db.gibSprachwahl ().lokal,
	ObjektAufzaehlung.FENSTER);
    }
    if (art.equals ("THEKE"))
    {
      oap = new ObjektAnlegenPanel (db.gibSprachwahl ().lokal,
	ObjektAufzaehlung.THEKE);
    }

    if (art.toUpperCase ().equals ("TUER"))
    {
      oap.gibOk ().addActionListener (
	new OapBuOkListener (ObjektAufzaehlung.TUER));
    }
    if (art.toUpperCase ().equals ("FENSTER"))
    {
      oap.gibOk ().addActionListener (
	new OapBuOkListener (ObjektAufzaehlung.FENSTER));
    }
    if (art.toUpperCase ().equals ("THEKE"))
    {
      oap.gibOk ().addActionListener (
	new OapBuOkListener (ObjektAufzaehlung.THEKE));
    }
    oap.setLocationRelativeTo (this);
    oap.gibCa ().addActionListener (new OapBuCaListener ());
    t = objekt;

    /* bearbeitet gibt an, dass der Aufruf von regalBearbeiten kommt */
    setzeBearbeitet (true);
    markiertesRechteck = objekt;

    /*
     * Die Zeichenkette "neuesObjekt" ist ein Code, der bei der
     * Lokalisierung in einen Info-Text uebersetzt wird.
     */
    oap.gibTxt_info ().setText (lokal.gibUebersetzung ("neuesObjekt"));

    oap.setzeVoreingetrageneDaten (t.width, t.height);

    /* Deaktiviere Hintergrundfenster solange sap offen ist. */
    this.setEnabled (false);
  }


  /**
   * Dreht das gezeichnete Rechteck, welches das Regal darstellt, um 90
   * Grad.
   */
  private void regalDrehen()
  {
    ArrayList<Rectangle> temp;
    Rectangle rechteck;
    temp = new ArrayList<Rectangle> ();

    for (FigurZustand fz : std.gibAlleZustaendeListen ())
    {
      temp.add (new Rectangle (fz.x, fz.y, fz.width * MASSSTAB,
	fz.height * MASSSTAB));
    }
    rechteck = new Rectangle (markiertesRechteck.x,
      markiertesRechteck.y, markiertesRechteck.width * MASSSTAB,
      markiertesRechteck.height * MASSSTAB);

    temp.remove (temp.indexOf (rechteck));

    rechteck = new Rectangle (markiertesRechteck.x,
      markiertesRechteck.y, markiertesRechteck.height * MASSSTAB,
      markiertesRechteck.width * MASSSTAB);

    if (kollisionErkennen (rechteck, temp))
    {
      JOptionPane.showMessageDialog (null,lokal.gibUebersetzung 
	("Bitte platzieren sie das Objekt an einer anderen "
	+ "Stelle."));
    }
    else
    {
      std.inAllenListenAendern (markiertesRechteck,
	standortBezeichner.getText ());
      zeichenblatt.validate ();
      repaint ();
    }
  }


  /**
   * Dreht das gezeichnete Objekt, welches das Regal darstellt, um 90
   * Grad.
   */
  private void objektDrehen()
  {
    int hoehe;

    hoehe = markiertesRechteck.height;
    markiertesRechteck.height = markiertesRechteck.width;
    markiertesRechteck.width = hoehe;

    zeichenblatt.validate ();
    repaint ();
  }


  /**
   * Laedt die Koordinate des Mauszeigers.
   * 
   * @return Die gespeicherte Position der Maus
   * @see setzeKoordinateMaus (Point koordinateMaus)
   */
  private Point gibKoordinateMaus()
  {
    return koordinateMaus;
  }


  private int setzeFensterPositionX()
  {
    return ((Toolkit.getDefaultToolkit ().getScreenSize ().height 
      - getHeight ()) / 2);
  }


  /**
   * Beschreibung: Zeichnet alle Regale, die sich in der RechteckListe
   * befinden.
   * 
   * @see Datenbank#gibRechteckListe()
   * @param g
   *          Grafik-Objekt
   */
  private void zeichneRechtecke(Graphics g)
  {
    FigurZustand r;
    Iterator<FigurZustand> it;

    g.clearRect (0, 0, getSize ().width, getSize ().height);
    g.setColor (regalFarbe);

    /* Zeichne Regale */
    for (it = std.gibRechteckListe ().iterator (); it.hasNext ();)
    {
      r = it.next ();
      if (r != null)
      {
	g.drawRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	g.fillRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
      }
    }

    if (std.gibObjekte (ObjektAufzaehlung.TUER) != null)
    {
      /* Zeichne Tueren */
      for (it = std.gibObjekte (ObjektAufzaehlung.TUER).iterator (); 
	it.hasNext ();)
      {
	r = it.next ();
	if (r != null)
	{
	  g.setColor (tuerFarbe);
	  g.drawRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	  g.fillRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	}
      }
    }
    if (std.gibObjekte (ObjektAufzaehlung.FENSTER) != null)
    {
      /* Zeichne Fenster */
      for (it = std.gibObjekte (ObjektAufzaehlung.FENSTER).iterator (); 
	it.hasNext ();)
      {
	r = it.next ();
	if (r != null)
	{
	  g.setColor (fensterFarbe);
	  g.drawRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	  g.fillRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	}
      }
    }
    if (std.gibObjekte (ObjektAufzaehlung.THEKE) != null)
    {
      /* Zeichne Theken */
      for (it = std.gibObjekte (ObjektAufzaehlung.THEKE).iterator (); 
	it.hasNext ();)
      {
	r = it.next ();
	if (r != null)
	{
	  g.setColor (thekenFarbe);
	  g.drawRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	  g.fillRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
	}
      }
    }
    if (markiertesRechteck != null)
    {
      r = markiertesRechteck;
      g.setColor (markierungsFarbe);
      g.drawRect (r.x, r.y, r.width * MASSSTAB, r.height * MASSSTAB);
    }
  }


  /**
   * Beschreibung: Laesst den Benutzer Objektgruppen faerben.
   * 
   * @see Datenbank#speichereBibliothek(String)
   * @info Methode wurde aus Zeitgruenden nicht mehr implementiert.
   */
  private void faerben()
  {
    String[] objekte;
    String standort;

    objekte = new String[4];
    objekte[0] = "Regale";
    objekte[1] = "Fenster";
    objekte[2] = "Tueren";
    objekte[3] = "Theken";

    standort = (String) JOptionPane.showInputDialog (null,
      lokal.gibUebersetzung ("Bitte waehlen Sie "
	+ "sie Objektgruppe, die Sie faerben moechten."),
      lokal.gibUebersetzung ("Gruppe waehlen"),
      JOptionPane.PLAIN_MESSAGE, null, objekte,
      JOptionPane.INFORMATION_MESSAGE);
    if (standort.equals ("Regale"))
    {
    }
    if (standort.equals ("Fenster"))
    {
    }
    if (standort.equals ("Tueren"))
    {
    }
    if (standort.equals ("Theken"))
    {
    }
  }


  /**
   * Beschreibung: Speichert die aktuelle Bibliothek.
   * 
   * @see Datenbank#speichereBibliothek(String)
   */
  private void speichern()
  {
    db.speichereBibliothek (standortBezeichner.getText (), std);
  }


  /**
   * Beschreibung: Speichert die aktuelle Bibliothek unter dem
   * angebebenen Namen.
   * 
   * @see Datenbank#speichereBibliothek(String)
   */
  private void speichernUnter(String speicherName)
  {
    db.speichereBibliothek (speicherName, std);
  }


  /**
   * Laedt die ausgewaehlte Bibliothek.
   * 
   * @see Datenbank#ladeBibliothek(String)
   */
  private boolean laden()
  {
    String standort;
    String ar[];
    int dimensionen[];
    ar = db.gibVorhandeneBibliotheken ();

    standort = (String) JOptionPane.showInputDialog (null,
      lokal.gibUebersetzung ("Bitte waehlen Sie den Standort\nder zu " +
      "ladenden Bibliothek."), lokal.gibUebersetzung 
      ("Bibliothek waehlen"), JOptionPane.PLAIN_MESSAGE, null, ar,
      JOptionPane.INFORMATION_MESSAGE);
    if ( (standort != null) && (standort.length () > 0))
    {
      if (buttonR == null)
      {
	erzeugeFenster (sprache);
      }
      try
      {
	std = db.ladeBibliothek (standort);
	standortBezeichner.setText (standort);
	dimensionen = new int[2];
	dimensionen = db.gibStandortDaten (standort);
	standortMasse.setText (dimensionen[0] + "x" + dimensionen[1]);
	zeichenblatt.setPreferredSize (new Dimension (dimensionen[0]
	  * std.gibMASSSTAB (), dimensionen[1] * std.gibMASSSTAB ()));
	MASSSTAB = std.gibMASSSTAB ();
	repaint ();
	return true;
      }
      catch (NullPointerException npex)
      {
	JOptionPane.showMessageDialog (null,
	  lokal.gibUebersetzung ("Kein Standort gefunden."));
      }
    }
    else
    {
      JOptionPane.showMessageDialog (null, lokal
	.gibUebersetzung ("Bitte waehlen Sie einen vorhandenen "
	  + "Standort."));
    }
    return false;
  }


  /**
   * Loescht die ausgewaehlte Bibliothek.
   * 
   * @see Datenbank#ladeBibliothek(String)
   */
  private void loeschen()
  {
    String standort;
    int auswahl;
    String ar[], optionen[];
    ar = db.gibVorhandeneBibliotheken ();

    standort = (String) JOptionPane.showInputDialog (null,
      lokal
	.gibUebersetzung ("Bitte waehlen Sie den Standort\nder zu "
	  + "loeschenden Bibliothek."),
      lokal.gibUebersetzung ("Bibliothek loeschen"),
      JOptionPane.PLAIN_MESSAGE, null, ar,
      JOptionPane.INFORMATION_MESSAGE);
    if ( (standort != null) && (standort.length () > 0))
    {
      optionen = new String[2];
      optionen[0] = lokal.gibUebersetzung ("Ja");
      optionen[1] = lokal.gibUebersetzung ("Nein");

      auswahl = JOptionPane.showOptionDialog (
	null,
	lokal
	  .gibUebersetzung ("Moechten Sie die aktuelle Bibliothek "
	    + "am Standort ")
	  + standort
	  + lokal.gibUebersetzung (" wirklich loeschen?"),
	lokal.gibUebersetzung ("Achtung!"),
	JOptionPane.YES_NO_CANCEL_OPTION,
	JOptionPane.QUESTION_MESSAGE, null, optionen, null);

      switch (auswahl)
      {
	case 0:
	  /*
	   * Falls der geloeschte Standort der aktuelle ist, gebe
	   * Fehlermeldung aus.
	   */
	  if (standort.equals (standortBezeichner.getText ()))
	  {
	    JOptionPane.showMessageDialog (null,lokal.gibUebersetzung 
	      ("Ein geladener Standort kann nicht geloescht werden"));
	  }
	  else
	  {
	    db.loescheBibliothek (standort);
	  }
	  break;
	default:
	  ; /* tue nichts */
      }

    }
    else
    {
      JOptionPane.showMessageDialog (null, lokal.gibUebersetzung 
	("Bitte waehlen Sie einen vorhandenen Standort."));
    }
  }


  /**
   * Fragt die gewuenschte Sprache in einem Dialog ab und setzt
   * entsprechend das Lokalisierungsobjekt
   */
  private void spracheWaehlen()
  {
    String sprache;
    String[] sprachen;
    sprachen = new String[3];
    sprachen[0] = "Deutsch";
    sprachen[1] = "English";
    sprachen[2] = "Francais";

    sprache = (String) JOptionPane.showInputDialog (null,
      lokal.gibUebersetzung ("Bitte waehlen Sie die zuverwendende" +
      "\nSprache."), lokal.gibUebersetzung ("Spache waehlen"), 
      JOptionPane.PLAIN_MESSAGE, null, sprachen,
      JOptionPane.INFORMATION_MESSAGE);

    /* Falls Abbrechen geklickt wurde, darf nichts passieren */
    if (sprache != null)
    {
      if (sprache.equals ("English"))
      {
	sprache = "Englisch";
      }
      if (sprache.equals ("Francais"))
      {
	sprache = "Franzoesisch";
      }

      db.setzeSprachwahl (new Sprachwahl (sprache));
      lokal = db.gibSprachwahl ().lokal;
      uebersetzen (lokal);
    }
  }


  /**
   * Uebersetzt die Objekte, die bereits initialisiert sind. Alle
   * anderen werden zur Laufzeit uebersetzt.
   * 
   * @param lokal
   */
  private void uebersetzen(Lokalisierung lokal)
  {
    /*
     * Wenn die Schaltflaechen noch nicht existieren, uebersetze sie
     * nicht.
     */
    if (buttonR != null)
    {
      buttonR.setText (lokal.gibUebersetzung ("Regal hinzufuegen"));
      buttonT.setText (lokal.gibUebersetzung ("Tuer hinzufuegen"));
      buttonTh.setText (lokal.gibUebersetzung ("Theke hinzufuegen"));
      buttonF.setText (lokal.gibUebersetzung ("Fenster hinzufuegen"));
    }
    standortBezText.setText (lokal.gibUebersetzung ("Standort: "));
    standortMasText.setText (lokal.gibUebersetzung ("Masse: "));

    /*
     * Uebersetze Standort nur mit, wenn er mit dem gesuchten Muster
     * uebereinstimmt. Somit werden keine Standortnamen uebersetzt.
     * Muster: --XXXX(X)-- | X = beliebiger Buchstabe, also --empty--,
     * --leer--, --vide--, ...
     */
    if (Pattern.matches ("\\-{2}.{4,5}\\-{2}",
      standortBezeichner.getText ()))
    {
      standortBezeichner.setText (lokal.gibUebersetzung ("--leer--"));
      standortMasse.setText (lokal.gibUebersetzung ("--leer--"));
    }
    menuItem1.setText (lokal
      .gibUebersetzung ("Neue Bibliothek anlegen"));
    menuItem2.setText (lokal.gibUebersetzung ("Bibliothek laden"));
    menuItem3.setText (lokal.gibUebersetzung ("Bibliothek speichern"));
    menuItem4.setText (lokal.gibUebersetzung ("Schliessen"));
    menuItem5.setText (lokal.gibUebersetzung ("Standort aendern"));
    menuItem6.setText (lokal.gibUebersetzung ("Objekt loeschen"));
    menuItem7.setText (lokal.gibUebersetzung ("Objekt bearbeiten"));
    menuItem8.setText (lokal.gibUebersetzung ("Objekt drehen"));
    menuItem9.setText (lokal.gibUebersetzung ("Listen ausgeben"));
    menuItem11.setText (lokal.gibUebersetzung ("Sprache waehlen"));
    menuItem12.setText (lokal
      .gibUebersetzung ("Bibliothek speichern unter..."));
    menuItem13.setText (lokal.gibUebersetzung ("Bibliothek loeschen"));
    menuD.setText (lokal.gibUebersetzung ("Datei"));
    menuB.setText (lokal.gibUebersetzung ("Bearbeiten"));
    menuA.setText (lokal.gibUebersetzung ("Ansicht"));
  }


  /**
   * Liefert das Datenbankobjekt zurueck, dass der Editor beim
   * Initialisieren erzeugt. Die Fassade legt davon eine Kopie an mit
   * der sie arbeitet.
   * 
   * @return Datenbankobjekt
   * @see FassadeBibVis#legeBibVisAn()
   */
  protected Datenbank gibDatenbank()
  {
    return db;
  }


  /**
   * Erkennt, ob sich das zu zeichnende Regal innerhalb des
   * Zeichenbereichs befindet und prueft dann, ob es mit einem anderen
   * kollidiert.
   * 
   * @param rechteck
   * @return
   */
  private boolean kollisionErkennen(Rectangle rechteck,
    ArrayList<Rectangle> al)
  {
    if (new Rectangle (0, 0, zeichenblatt.getWidth (),
      zeichenblatt.getHeight ()).contains (rechteck))
    {
      for (Rectangle e : al)
      {
	if (rechteck.intersects (e))
	{
	  return true;
	}
      }
      return false;
    }
    else
    {
      return true;
    }
  }


  /**
   * Variable bearbeitet wird gesetzt, die gebraucht wird, um
   * anzuzeigen, dass der Methodenaufruf im RapBuOkListener von
   * regalBeaerbeiten(Regal) kommt.
   * 
   * @param bearbeitet
   */
  private void setzeBearbeitet(boolean bearbeitet)
  {
    this.bearbeitet = bearbeitet;
  }


  private void setzeTyp(ObjektAufzaehlung typ)
  {
    this.typ = typ;
  }


  private ObjektAufzaehlung gibTyp()
  {
    return typ;
  }


  /**
   * Speichert die Koordinate des Mauszeigers an der uebergebenen
   * Position.
   * 
   * @param koordinateMaus
   *          Die aktuelle Position der Maus
   * @see gibKoordinateMaus ()
   */
  private void setzeKoordinateMaus(Point koordinateMaus)
  {
    this.koordinateMaus = koordinateMaus;
  }


  protected void schliessen()
  {
    FassadeBibVis.gesperrt = false;
    dispose ();
  }

  private class Zeichenblatt extends JPanel
  {
    private static final long serialVersionUID = -1276697544598863480L;


    @Override
    public void paintComponent(Graphics g)
    {
      zeichneRechtecke (g);
    }
  }

  private class DateiNeueBibAnlegenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      int auswahl;
      String[] optionen;

      if (std.gibVeraendert ())
      {
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");

	auswahl = JOptionPane.showOptionDialog (null,lokal
	  .gibUebersetzung ("Moechten Sie die aktuelle Bibliothek "
	  + "am Standort ") + standortBezeichner.getText ()
	  + lokal.gibUebersetzung (" speichern?"),
	    lokal.gibUebersetzung ("Achtung!"),
	    JOptionPane.YES_NO_CANCEL_OPTION,
	    JOptionPane.QUESTION_MESSAGE, null, optionen, null);

	switch (auswahl)
	{
	  case 0:
	    speichern ();
	    neueBibAnlegen ();
	    break;
	  case 1:
	    neueBibAnlegen ();
	    break;
	  default:
	    ; /* tue nichts */
	}
      }
      else
      {
	neueBibAnlegen ();
      }
    }
  }

  private class DateiBibLadenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      boolean ok = laden ();
      if (! (buttonR.isEnabled ()) && ok)
      {
	aktiviereSchaltflaechen ();
	menuB.setVisible (true);
      }
    }
  }

  private class DateiBibSpeichernListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      speichern ();
      menuItem3.setEnabled (false);
      std.setzeVeraendert (false);
    }
  }

  private class DateiBibSpeichernUnterListener implements
    ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      String s = (String) JOptionPane.showInputDialog (null,
	lokal.gibUebersetzung ("SpeichernUnterText"),
	lokal.gibUebersetzung ("SpeichernUnterTitel"),
	JOptionPane.PLAIN_MESSAGE, null, null,
	standortBezeichner.getText ());

      if (db.standortVorhanden (s))
      {
	int auswahl;
	String[] optionen;
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");
	auswahl = JOptionPane.showOptionDialog (null,
	  lokal.gibUebersetzung ("Standortname bereits vorhanden. "
	    + "Ueberschreiben?"),
	  lokal.gibUebersetzung ("Achtung!"),
	  JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE,
	  null, optionen, null);
	switch (auswahl)
	{
	  case 0:
	    speichernUnter (s);
	    menuItem3.setEnabled (false);
	    std.setzeVeraendert (false);
	    break;
	  default:
	    ; /* tue nichts */
	}
      }
      else
      {
	speichernUnter (s);
	menuItem3.setEnabled (false);
	std.setzeVeraendert (false);
      }
    }
  }

  private class DateiBibLoeschenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      loeschen ();
    }
  }

  private class DateiSchliessenListener implements ActionListener
  {

    @Override
    public void actionPerformed(ActionEvent e)
    {
      if (std.gibVeraendert ())
      {
	int auswahl;
	String[] optionen;
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");
	auswahl = JOptionPane.showOptionDialog (null,lokal
	  .gibUebersetzung ("Moechten Sie vor dem Beenden speichern?"),
	  lokal.gibUebersetzung ("Achtung!"),
	  JOptionPane.YES_NO_CANCEL_OPTION,
	  JOptionPane.QUESTION_MESSAGE, null, optionen, null);
	switch (auswahl)
	{
	  case 0:
	    speichern ();
	    schliessen ();
	    break;
	  case 1:
	    schliessen ();
	    break;
	  default:
	    ; /* tue nichts */
	}
      }
      else
      {
	schliessen ();
      }
    }
  }

  private class ZeichenblattListener implements MouseListener
  {

    @Override
    public void mouseClicked(MouseEvent e)
    {
      boolean gefunden;
      Iterator<FigurZustand> it;
      FigurZustand r;
      Point p;

      gefunden = false;
      p = e.getPoint ();

      for (it = std.gibRechteckListe ().iterator (); it.hasNext ();)
      {
	r = it.next ();

	if ( (p.x >= r.x) && (p.x <= (r.x + (r.width * MASSSTAB)))
	  && (p.y >= r.y) && (p.y <= (r.y + (r.height * MASSSTAB))))
	{
	  markiertesRechteck = r;
	  gefunden = true;
	  /* Rechtsklick auf Regal simulieren */
	  if (e.getButton () == MouseEvent.BUTTON3)
	  {
	    /*
	     * PopUpMenue anzeigen bei Rechtsklick. Leider aus Zeit-
	     * gruenden nur rudimentaer implementiert.
	     */

	    JOptionPane.showMessageDialog (
	      null,
	      lokal.gibUebersetzung (":\n"
		+ std.gibZuordnungZR ().get (r).regalInfo ()));
	  }
	}
      }

      for (ObjektAufzaehlung art : ObjektAufzaehlung.values ())
      {
	for (it = std.gibObjektListe ().get (art).iterator (); it
	  .hasNext ();)
	{
	  r = it.next ();
	  if ( (p.x >= r.x) && (p.x <= (r.x + (r.width * MASSSTAB)))
	    && (p.y >= r.y) && (p.y <= (r.y + (r.height * MASSSTAB))))
	  {
	    markiertesRechteck = r;
	    setzeTyp (art);
	    gefunden = true;
	    /* Rechtsklick auf Objekt simulieren */
	    if (e.getButton () == MouseEvent.BUTTON3)
	    {
	      /*
	       * PopUpMenue aus Zeitgruenden nicht implementiert. int
	       * index = std. gibObjektListe ().get (art).indexOf (r);
	       * System.out.println ("Objektdaten:\n" +
	       * std.gibObjektListe ().get (art).get (index) .toString
	       * ()); System.out.println
	       * ("\n------------------------------\n");
	       */
	    }
	  }
	}
      }
      if (!gefunden)
      {
	markiertesRechteck = null;
      }
    }


    @Override
    public void mouseEntered(MouseEvent e)
    {
      eintritt = true;
    }


    @Override
    public void mouseExited(MouseEvent e)
    {
      eintritt = false;
    }


    @Override
    public void mousePressed(MouseEvent e)
    {
      /* tue dasselbe wie bei "mouseClicked(MouseEvent e)" */
      mouseClicked (e);
    }


    @Override
    public void mouseReleased(MouseEvent e)
    {
      /* tue nichts. */
    }
  }

  private class ButtonDeaktiviertListener implements MouseListener
  {

    @Override
    public void mouseClicked(MouseEvent e)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseEntered(MouseEvent e)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseExited(MouseEvent e)
    {
      /* tue nichts. */
    }


    @Override
    public void mousePressed(MouseEvent e)
    {
      JOptionPane.showMessageDialog (null,
	lokal.gibUebersetzung ("deaktiviert"),
	lokal.gibUebersetzung ("Achtung!"),
	JOptionPane.WARNING_MESSAGE);
    }


    @Override
    public void mouseReleased(MouseEvent e)
    {
      /* tue nichts. */
    }
  }

  private class ButtonObjektHinzufuegenListener implements
    MouseListener
  {
    private ObjektAufzaehlung art;


    public ButtonObjektHinzufuegenListener (ObjektAufzaehlung art)
    {
      this.art = art;
    }


    @Override
    public void mouseClicked(MouseEvent e)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseEntered(MouseEvent e)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseExited(MouseEvent e)
    {
      /* tue nichts. */
    }


    /*
     * Setze markiertes Rechteck zurueck, um neues erzeugen zu koennen.
     */
    @Override
    public void mousePressed(MouseEvent e)
    {
      markiertesRechteck = null;
      repaint ();
    }


    @Override
    public void mouseReleased(MouseEvent e)
    {
      if (eintritt)
      {
	setzeKoordinateMaus (zeichenblatt.getMousePosition ());
	if (art == null)
	{
	  regalHinzufuegenButton ();
	}
	else
	{
	  objektHinzufuegenButton (art);
	}
	std.setzeVeraendert (true);
	menuItem3.setEnabled (true);
      }
      else
      {
	JOptionPane.showMessageDialog (null, lokal
	  .gibUebersetzung ("Bitte ziehen Sie das Objekt zuerst "
	    + "in die Bibliothek"));
      }
    }
  }

  private class BearbeitenStandortAendernListener implements
    ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      standortAendern ();
    }
  }

  private class BearbeitenLoeschenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      try
      {
	if (markiertesRechteck != null)
	{
	  if (std.gibZuordnungZR ().get (markiertesRechteck) != null)
	  {
	    regalLoeschen (std.gibZuordnungZR ().get (
	      markiertesRechteck));
	  }
	  else
	  {
	    objektLoeschen (markiertesRechteck);
	  }
	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);
	}
	else
	{
	  throw new NichtMarkiertAusnahme ();
	}
      }
      catch (NichtMarkiertAusnahme nmex)
      {
	JOptionPane
	  .showMessageDialog (null, lokal
	    .gibUebersetzung ("Kein Regal zum Loeschen markiert."));
      }
    }
  }

  private class BearbeitenBearbeitenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      try
      {
	if (markiertesRechteck != null)
	{
	  if (std.gibZuordnungZR ().get (markiertesRechteck) != null)
	  {
	    regalBearbeiten (std.gibZuordnungZR ().get (
	      markiertesRechteck));
	  }
	  else
	  {
	    objektBearbeiten (markiertesRechteck, gibTyp ().toString ());
	  }
	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);
	}
	else
	{
	  throw new NichtMarkiertAusnahme ();
	}
      }
      catch (NichtMarkiertAusnahme nmex)
      {
	JOptionPane.showMessageDialog (null, lokal
	  .gibUebersetzung ("Kein Objekt zum Bearbeiten markiert."));
      }
    }
  }

  private class BearbeitenRegalDrehenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      try
      {
	if (markiertesRechteck != null)
	{
	  if (std.gibZuordnungZR ().get (markiertesRechteck) != null)
	  {
	    regalDrehen ();
	  }
	  else
	  {
	    objektDrehen ();
	  }
	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);
	}
	else
	{
	  throw new NichtMarkiertAusnahme ();
	}
      }
      catch (NichtMarkiertAusnahme nmex)
      {
	JOptionPane.showMessageDialog (null,
	  lokal.gibUebersetzung ("Kein Objekt zum Drehen markiert."));
      }
    }
  }

  private class BearbeitenFaerbenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      faerben ();
    }
  }

  /*
   * Debug-Listener
   */
  // private class BearbeitenListenAusgebenListener implements
  // ActionListener
  // {
  // @Override
  // public void actionPerformed (ActionEvent e)
  // {
  // std.listenAusgeben ();
  // db.listenAusgeben ();
  // }
  // }

  private class AnsichtSpracheWaehlenListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      spracheWaehlen ();
    }
  }

  /**
   * ActionListener "horcht" auf die OK-Schaltflaeche der
   * StandortAnlegenMaske. Wird der Listener aktiviert, prueft er, ob
   * der Standort bereits vorhanden ist und wirft eine Exception.
   * Ansonsten wird der Standort in den jeweiligen Listen gespeichert.
   * 
   * @see Standortverwalter#standortHinzufuegen(String, String, int,
   *      String, String, int, int)
   * @exception StandortBereitsVorhandenAusnahme
   *              , UngueltigeEingabeAusnahme
   * 
   */
  private class SapBuOkListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      int laenge, breite, id;
      boolean ausnahme;
      String bezeichner;
      int dimensionen[];

      try
      {
	/* Pruefe, ob schon ein Standort angelegt worden ist */
	if (db.standortVorhanden (sap.gibTxt_bezeichner ().getText ()))
	{

	  // idS = std.gibZuordnungSI ().get (
	  // sap.gibTxt_bezeichner ().getText ());
	  //
	  // if (db.gibStandort ().standortVorhanden (idS))
	  // {
	  throw new StandortBereitsVorhandenAusnahme (
	    lokal.gibUebersetzung ("Standort bereits vorhanden."));
	  // }
	}
	else
	{
	  ausnahme = false;

	  if (sap.gibTxt_bezeichner ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_bezeichner ().setBackground (Color.RED);
	  }
	  if (sap.getTxt_ort ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.getTxt_ort ().setBackground (Color.RED);
	  }
	  if (sap.gibTxt_plz ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_plz ().setBackground (Color.RED);
	  }
	  if (sap.gibTxt_hausnummer ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_hausnummer ().setBackground (Color.RED);
	  }
	  if (sap.gibTxt_strasse ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_strasse ().setBackground (Color.RED);
	  }
	  if (sap.gibTxt_laenge ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_laenge ().setBackground (Color.RED);
	  }
	  if (sap.gibTxt_breite ().getText ().isEmpty ())
	  {
	    ausnahme = true;
	    sap.gibTxt_breite ().setBackground (Color.RED);
	  }
	  if (ausnahme)
	  {
	    throw new LeeresEingabefeldAusnahme (lokal);
	  }

	  laenge = Integer.parseInt (sap.gibTxt_laenge ().getText ());
	  breite = Integer.parseInt (sap.gibTxt_breite ().getText ());

	  if (laenge <= 0)
	  {
	    throw new ZahlGroesserNullAusnahme ("Laenge", lokal);
	  }
	  if (breite <= 0)
	  {
	    throw new ZahlGroesserNullAusnahme ("Breite", lokal);
	  }

	  bezeichner = sap.gibTxt_bezeichner ().getText ();

	  dimensionen = new int[2];
	  dimensionen[0] = laenge;
	  dimensionen[1] = breite;
	  std.setzeDimensionen (dimensionen);

	  /* fuege den Standort dem Standortverwalter hinzu */
	  db.gibStandort ().standortHinzufuegen (bezeichner,
	    sap.getTxt_ort ().getText (),
	    sap.gibTxt_plz ().getText (),
	    sap.gibTxt_hausnummer ().getText (),
	    sap.gibTxt_strasse ().getText (), laenge, breite);

	  /*
	   * hole die aktuelle Standort-ID und fuege sie zusammen mit
	   * dem Standort der Zuordnungs-HashMap hinzu
	   */
	  id = db.gibStandort ().gibStandortIdTemp ();

	  db.gibStandort ().gibZuordnungIS ()
	    .put (id, db.gibStandort ().gibStandort (id));

	  /* schliesse sap-Fenster */
	  sap.dispose ();

	  markiertesRechteck = null;

	  setzeEditorFenster (bezeichner, laenge, breite);
	  std.setzeMASSSTAB (MASSSTAB);
	  std.gibZuordnungSI ().put (standortBezeichner.getText (), id);

	  if (! (buttonR.isEnabled ()))
	  {
	    aktiviereSchaltflaechen ();
	  }
	  /* Aktiviere Hintergrundfenster wieder. */
	  setEnabled (true);
	}
      }
      catch (StandortBereitsVorhandenAusnahme sbvex)
      {
	JOptionPane.showMessageDialog (null, sbvex.getMessage (), sbvex
	  .getClass ().getName (), JOptionPane.WARNING_MESSAGE);
      }
      catch (UngueltigeEingabeAusnahme ueaex)
      {
	if (ueaex.getMessage ().contains ("Hausnummer"))
	{
	  sap.gibTxt_hausnummer ().setBackground (Color.RED);
	}
	else
	{
	  sap.gibTxt_plz ().setBackground (Color.RED);
	}
	JOptionPane.showMessageDialog (null, ueaex.getMessage (), ueaex
	  .getClass ().getName (), JOptionPane.WARNING_MESSAGE);
      }
      catch (ZahlGroesserNullAusnahme zgnex)
      {
	if (zgnex.gibWert ().equals ("Laenge"))
	{
	  sap.gibTxt_laenge ().setBackground (Color.RED);
	}
	else
	{
	  sap.gibTxt_breite ().setBackground (Color.RED);
	}
	JOptionPane.showMessageDialog (null, zgnex.getMessage (),
	  zgnex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }
      catch (NichtImAlphabetAusnahme niaex)
      {
	JOptionPane.showMessageDialog (null, niaex.getMessage (), niaex
	  .getClass ().getName (), JOptionPane.WARNING_MESSAGE);
      }
      catch (LeeresEingabefeldAusnahme lefex)
      {
	JOptionPane.showMessageDialog (null, lefex.getMessage (),
	  lefex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }

    }
  }

  private class SapBuCaListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      sap.dispose ();
      /* Aktiviere Hintergrundfenster wieder. */
      setEnabled (true);
    }
  }

  /**
   * ActionListener "horcht" auf die OK-Schaltflaeche der Klasse
   * RegalAnlegenPanel. Dabei werden zwei Faelle unterschieden. 1. Es
   * wurde ein neues Regal angelegt: Erzeuge das neue Regal 2. Es wurde
   * ein vorhandenes Regal bearbeitet. Egal welcher Fall zutrifft wird
   * das Regal in die jeweiligen Listen intern (bibVis) und extern
   * (Medienverwaltung) eingekettet. Eine Ausnahme achtet darauf, dass
   * das Formular vollstaendig ausgefuellt wurde.
   */
  private class RapBuOkListener implements ActionListener
  {
    public void actionPerformed(ActionEvent e)
    {
      Regal regal;
      ArrayList<Rectangle> temp;
      FigurZustand aktuellesRechteck;
      FigurZustand r;
      String s;
      int index, id, sid, laenge, hoehe, breite, etagen, abschnitte;
      boolean ausnahme, kollision;

      r = markiertesRechteck;
      try
      {
	ausnahme = false;

	/* LeeresEingabefeldAusnahme */
	if (rap.gibTxt_laenge ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_laenge ().setBackground (Color.RED);
	}
	if (rap.gibTxt_hoehe ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_hoehe ().setBackground (Color.RED);
	}
	if (rap.gibTxt_breite ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_breite ().setBackground (Color.RED);
	}
	if (rap.gibTxt_etagen ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_etagen ().setBackground (Color.RED);
	}
	if (rap.gibTxt_abschnitte ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_abschnitte ().setBackground (Color.RED);
	}
	if (rap.gibTxt_bezeichner ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  rap.gibTxt_bezeichner ().setBackground (Color.RED);
	}
	if (ausnahme)
	{
	  throw new LeeresEingabefeldAusnahme (lokal);
	}
	/* ZahlGroesserNullAusnahme */
	s = "";

	if (Integer.parseInt (rap.gibTxt_laenge ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Laenge";
	  rap.gibTxt_laenge ().setBackground (Color.RED);
	}
	if (Integer.parseInt (rap.gibTxt_hoehe ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Hoehe";
	  rap.gibTxt_hoehe ().setBackground (Color.RED);
	}
	if (Integer.parseInt (rap.gibTxt_breite ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Breite";
	  rap.gibTxt_breite ().setBackground (Color.RED);
	}
	if (Integer.parseInt (rap.gibTxt_etagen ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Etagen";
	  rap.gibTxt_etagen ().setBackground (Color.RED);
	}
	if (Integer.parseInt (rap.gibTxt_abschnitte ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Abschnitte";
	  rap.gibTxt_abschnitte ().setBackground (Color.RED);
	}
	if (ausnahme)
	{
	  throw new ZahlGroesserNullAusnahme (s, lokal);
	}

	/*
	 * Erzeuge eine temporaere Liste aller Regale, um sie dann auf
	 * Kollisionen zu pruefen
	 */
	temp = new ArrayList<Rectangle> ();

	for (FigurZustand fz : std.gibAlleZustaendeListen ())
	{
	  temp.add (new Rectangle (fz.x, fz.y, fz.width * MASSSTAB,
	    fz.height * MASSSTAB));
	}

	/* Falls der Aufruf von "Bearbeiten" kam, loesche altes Regal */
	if (bearbeitet)
	{
	  index = temp.indexOf (new Rectangle (r.x, r.y, r.width
	    * MASSSTAB, r.height * MASSSTAB));
	  temp.remove (index);
	}
	else
	{
	  r = new FigurZustand (gibKoordinateMaus ().x,
	    gibKoordinateMaus ().y, Integer.parseInt (rap
	      .gibTxt_laenge ().getText ()), Integer.parseInt (rap
	      .gibTxt_breite ().getText ()));
	}
	/* Pruefe auf Kollision */
	kollision = kollisionErkennen (
	  new Rectangle (r.x, r.y, Integer.parseInt (rap
	    .gibTxt_laenge ().getText ()) * MASSSTAB,
	    Integer.parseInt (rap.gibTxt_breite ().getText ())
	      * MASSSTAB), temp);
	if (!kollision)
	{

	  id = -1;
	  /* Pruefe, ob Aufruf von RegalBearbeiten */
	  if (bearbeitet)
	  {
	    /* Hole ID des bearbeiteten Regals */
	    id = std.gibZuordnungZR ().get (markiertesRechteck)
	      .gibRegalId ();

	    /* Loesche "altes" Regal, bevor neues generiert wird */
	    std.ausAllenListenLoeschen (std.gibZuordnungZR ().get (
	      markiertesRechteck));

	    /* Schittstelle */
	    sid = std.gibZuordnungSI ().get (
	      standortBezeichner.getText ());

	    if (db.gibStandort ().standortVorhandenTemp (sid))
	    {
	      db.gibStandort ().gibStandortTemp (sid)
		.regalEntfernen (id);
	    }
	    else
	    {
	      db.gibStandort ().gibStandort (sid).regalEntfernen (id);
	    }
	  }
	  Point p = gibKoordinateMaus ();

	  /* Hole Daten des Regals aus der Eingabemaske */
	  laenge = Integer.parseInt (rap.gibTxt_laenge ().getText ());
	  hoehe = Integer.parseInt (rap.gibTxt_hoehe ().getText ());
	  breite = Integer.parseInt (rap.gibTxt_breite ().getText ());
	  etagen = Integer.parseInt (rap.gibTxt_etagen ().getText ());
	  abschnitte = Integer.parseInt (rap.gibTxt_abschnitte ()
	    .getText ());
	  regal = new Regal (laenge, hoehe, breite, etagen, abschnitte,
	    standortBezeichner.getText ());
	  if (bearbeitet)
	  {
	    regal.setzeId (id);

	    /* Unterstuetze Garbage Collection */
	    markiertesRechteck = null;
	    setzeBearbeitet (false);

	    aktuellesRechteck = new FigurZustand (r.x, r.y, laenge,
	      breite);
	  }
	  else
	  {
	    aktuellesRechteck = new FigurZustand (p.x, p.y, laenge,
	      breite);
	  }
	  std.gibRechteckListe ().add (aktuellesRechteck);
	  std.gibRegalListe ().add (regal);
	  std.gibZuordnungZR ().put (aktuellesRechteck, regal);
	  std.gibZuordnungRZ ().put (regal, aktuellesRechteck);

	  /* Schittstelle */

	  sid = std.gibZuordnungSI ().get (
	    standortBezeichner.getText ());

	  /*
	   * Falls der Standort neu erzeugt wurde, lade Regal in
	   * temporaere Liste, ansonsten in persistente Liste
	   */
	  if (db.gibStandort ().gibStandortTemp (sid) != null)
	  {
	    db.gibStandort ().gibStandortTemp (sid)
	      .regalHinzufuegen (regal);
	  }
	  else
	  {
	    db.gibStandort ().gibStandort (sid)
	      .regalHinzufuegen (regal);
	  }

	  /* Unterstuetze ie Garbage Collection. */
	  aktuellesRechteck = null;
	  rap.dispose ();

	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);

	  /* Zeichne das Panel neu, um das Rechteck anzuzeigen. */
	  repaint ();
	}
	else
	{
	  JOptionPane.showMessageDialog (null, lokal
	    .gibUebersetzung ("Bitte einen anderen "
	      + "Stellplatz fuer das Regal aussuchen."));
	  rap.dispose ();
	}
	/* Aktiviere Hintergrundfenster wieder. */
	setEnabled (true);
      }
      catch (ZahlGroesserNullAusnahme zgnex)
      {
	if (zgnex.gibWert ().equals ("Laenge"))
	{
	  oap.gibTxt_laenge ().setBackground (Color.RED);
	}
	if (zgnex.gibWert ().equals ("Breite"))
	{
	  oap.gibTxt_breite ().setBackground (Color.RED);
	}
	JOptionPane.showMessageDialog (null, zgnex.getMessage (),
	  zgnex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }
      catch (LeeresEingabefeldAusnahme lefex)
      {
	JOptionPane.showMessageDialog (null, lefex.getMessage (),
	  lefex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }
    }
  }

  /**
   * ActionListener "horcht" auf die Abbrechen-Schaltflaeche der Klasse
   * RegalAnlegenPanel. Wird der Listener aktiviert, schliesst er
   * lediglich das Formular-Fenster rap und setzt vorher die
   * bearbeitet-Variable auf false.
   */
  private class RapBuCaListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      setzeBearbeitet (false);
      rap.dispose ();
      /* Aktiviere Hintergrundfenster wieder. */
      setEnabled (true);
    }
  }

  /**
   * ActionListener "horcht" auf die OK-Schaltflaeche der
   * StandortAnlegenMaske. Wird der Listener aktiviert, prueft er, ob
   * der Standort bereits vorhanden ist und wirft eine Exception.
   * Ansonsten wird der Standort in den jeweiligen Listen gespeichert.
   * 
   * @see Standortverwalter#standortHinzufuegen(String, String, int,
   *      String, String, int, int)
   * @exception StandortBereitsVorhandenAusnahme
   *              , UngueltigeEingabeAusnahme
   * 
   */
  private class OapBuOkListener implements ActionListener
  {
    private ObjektAufzaehlung art;


    public OapBuOkListener (ObjektAufzaehlung art)
    {
      this.art = art;
    }


    @Override
    public void actionPerformed(ActionEvent e)
    {
      FigurZustand aktuellesRechteck;
      FigurZustand r;
      String s;
      ArrayList<Rectangle> temp;
      boolean kollision, ausnahme;
      int index, laenge, breite;
      Point p;

      r = markiertesRechteck;

      try
      {
	ausnahme = false;

	/* LeeresEingabefeldAusnahme */
	if (oap.gibTxt_laenge ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  oap.gibTxt_laenge ().setBackground (Color.RED);
	}
	if (oap.gibTxt_breite ().getText ().isEmpty ())
	{
	  ausnahme = true;
	  oap.gibTxt_breite ().setBackground (Color.RED);
	}
	if (ausnahme)
	{
	  throw new LeeresEingabefeldAusnahme (lokal);
	}
	/* ZahlGroesserNullAusnahme */
	s = "";

	if (Integer.parseInt (oap.gibTxt_laenge ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Laenge";
	  oap.gibTxt_laenge ().setBackground (Color.RED);
	}
	if (Integer.parseInt (oap.gibTxt_breite ().getText ()) <= 0)
	{
	  ausnahme = true;
	  s = "Breite";
	  oap.gibTxt_breite ().setBackground (Color.RED);
	}
	if (ausnahme)
	{
	  throw new ZahlGroesserNullAusnahme (s, lokal);
	}

	temp = new ArrayList<Rectangle> ();

	for (FigurZustand fz : std.gibAlleZustaendeListen ())
	{
	  temp.add (new Rectangle (fz.x, fz.y, fz.width * MASSSTAB,
	    fz.height * MASSSTAB));
	}
	if (bearbeitet)
	{
	  index = temp.indexOf (new Rectangle (r.x, r.y, r.width
	    * MASSSTAB, r.height * MASSSTAB));
	  temp.remove (index);
	}
	else
	{
	  r = new FigurZustand (gibKoordinateMaus ().x,
	    gibKoordinateMaus ().y, Integer.parseInt (oap
	      .gibTxt_laenge ().getText ()), Integer.parseInt (oap
	      .gibTxt_breite ().getText ()));
	}
	kollision = kollisionErkennen (
	  new Rectangle (r.x, r.y, Integer.parseInt (oap
	    .gibTxt_laenge ().getText ()) * MASSSTAB,
	    Integer.parseInt (oap.gibTxt_breite ().getText ())
	      * MASSSTAB), temp);
	if (!kollision)
	{

	  p = gibKoordinateMaus ();
	  laenge = Integer.parseInt (oap.gibTxt_laenge ().getText ());
	  breite = Integer.parseInt (oap.gibTxt_breite ().getText ());

	  if (bearbeitet)
	  {
	    /* Loesche "altes" Objekt, bevor neues generiert wird */
	    std.gibObjektListe ().get (gibTyp ())
	      .remove (markiertesRechteck);

	    /* Unterstuetze Garbage Collection */
	    markiertesRechteck = null;

	    setzeBearbeitet (false);

	    aktuellesRechteck = new FigurZustand (r.x, r.y, laenge,
	      breite);
	  }
	  else
	  {
	    aktuellesRechteck = new FigurZustand (p.x, p.y, laenge,
	      breite);
	  }

	  std.gibObjektListe ().get (art).add (aktuellesRechteck);

	  /* Unterstuetze ie Garbage Collection. */
	  aktuellesRechteck = null;
	  oap.dispose ();
	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);

	  /* Zeichne das Panel neu, um das Rechteck anzuzeigen. */
	  repaint ();
	}
	else
	{
	  JOptionPane.showMessageDialog (null, lokal
	    .gibUebersetzung ("Bitte einen anderen "
	      + "Stellplatz fuer das Objekt aussuchen."));
	  oap.dispose ();
	}
	/* Aktiviere Hintergrundfenster wieder. */
	setEnabled (true);
      }
      catch (ZahlGroesserNullAusnahme zgnex)
      {
	if (zgnex.gibWert ().equals ("Laenge"))
	{
	  sap.gibTxt_laenge ().setBackground (Color.RED);
	}
	else
	{
	  sap.gibTxt_breite ().setBackground (Color.RED);
	}
	JOptionPane.showMessageDialog (null, zgnex.getMessage (),
	  zgnex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }
      catch (LeeresEingabefeldAusnahme lefex)
      {
	JOptionPane.showMessageDialog (null, lefex.getMessage (),
	  lefex.gibName (lokal), JOptionPane.WARNING_MESSAGE);
      }
    }
  }

  private class OapBuCaListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      oap.dispose ();
      /* Aktiviere Hintergrundfenster wieder. */
      setEnabled (true);
    }
  }

  /**
   * Der SapAendernBuOkListener (StandortAendernPanelButtonOkListener)
   * sorgt dafuer, dass
   * 
   */
  private class SapAendernBuOkListener implements ActionListener
  {
    @Override
    public void actionPerformed(ActionEvent e)
    {
      int index;
      int[] dimensionen;
      try
      {
	if (db.standortVorhanden (sap.gibTxt_bezeichner ().getText ()))
	{
	  throw new StandortBereitsVorhandenAusnahme (
	    lokal.gibUebersetzung ("Standort bereits vorhanden."));
	}
	else
	{
	  /* loesche die alten Standortdaten. */
	  // db.gibStandortDaten ().remove (standortBezeichner.getText
	  // ());

	  /*
	   * hole neue Daten, setze dann neue Raumgroesse und kette
	   * neuen Standort in Liste ein.
	   */
	  dimensionen = new int[2];
	  dimensionen[0] = Integer.parseInt (sap.gibTxt_laenge ()
	    .getText ());
	  dimensionen[1] = Integer.parseInt (sap.gibTxt_breite ()
	    .getText ());
	  std.setzeDimensionen (dimensionen);

	  // db.gibStandortDaten ().put (
	  // sap.getTxt_bezeichner ().getText (), dimensionen);
	  setzeEditorFenster (sap.gibTxt_bezeichner ().getText (),
	    dimensionen[0], dimensionen[1]);

	  /* Schnittstelle */
	  index = std.gibZuordnungSI ().get (
	    standortBezeichner.getText ());
	  db.gibStandort ()
	    .gibStandortTemp (index)
	    .allesAendern (sap.gibTxt_bezeichner ().getText (),
	      sap.getTxt_ort ().getText (),
	      sap.gibTxt_plz ().getText (),
	      sap.gibTxt_hausnummer ().getText (),
	      sap.gibTxt_strasse ().getText (), dimensionen[0],
	      dimensionen[1]);

	  sap.dispose ();
	  std.setzeVeraendert (true);
	  menuItem3.setEnabled (true);

	  /* Aktiviere Hintergrundfenster wieder. */
	  setEnabled (true);
	}
      }
      catch (StandortBereitsVorhandenAusnahme sbvex)
      {
	JOptionPane.showMessageDialog (null, sbvex.getMessage ());
      }
    }
  }

  /**
   * Der KollisionsListener sorgt dafuer, dass Objekte nicht ausserhalb
   * des Zeichenbereichs gezeichnet werden koennen und nicht miteinander
   * kollidieren.
   */
  private class KollisionsListener implements MouseListener
  {
    @Override
    public void mouseClicked(MouseEvent arg0)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseEntered(MouseEvent arg0)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseExited(MouseEvent arg0)
    {
      /* tue nichts. */
    }


    @Override
    public void mousePressed(MouseEvent arg0)
    {
      /* tue nichts. */
    }


    @Override
    public void mouseReleased(MouseEvent arg0)
    {
      /* Setzte Objekt wieder in den Zeichenbereich */
      FigurZustand r;
      ArrayList<Rectangle> temp;

      r = markiertesRechteck;
      if (r != null)
      {
	if ( (r.x + (r.width * MASSSTAB)) >= zeichenblatt.getWidth ())
	{
	  r.x = zeichenblatt.getWidth () - (r.width * MASSSTAB);
	}
	if (r.x <= 0)
	{
	  r.x = 0;
	}
	if ( (r.y + (r.height * MASSSTAB)) >= zeichenblatt.getHeight ())
	{
	  r.y = zeichenblatt.getHeight () - (r.height * MASSSTAB);
	}
	if (r.y <= 0)
	{
	  r.y = 0;
	}
      }

      /*
       * Kollisionserkennung: Ein Objekt muss markiert sein und es muss
       * bereits mehr als ein Objekt angelegt worden sein
       */
      if ( (r != null) && (std.gibAlleZustaendeListen ().size () > 1))
      {
	temp = new ArrayList<Rectangle> ();

	for (FigurZustand e : std.gibAlleZustaendeListen ())
	{
	  temp.add (new Rectangle (e.x, e.y, e.width * MASSSTAB,
	    e.height * MASSSTAB));
	}

	temp.remove (new Rectangle (r.x, r.y, r.width * MASSSTAB,
	  r.height * MASSSTAB));

	Rectangle ra = new Rectangle (r.x, r.y, (r.width * MASSSTAB)
	  + ZWISCHENRAUM, (r.height * MASSSTAB) + ZWISCHENRAUM);
	for (Rectangle e : temp)
	{
	  if (ra.intersects (e))
	  {
            JOptionPane.showMessageDialog (null,lokal.gibUebersetzung 
              ("Bitte platzieren sie das Objekt an einer anderen "
              + "Stelle."));
	    r.x = altX;
	    r.y = altY;
	  }
	}
      }
      einmal = true;
      repaint ();
    }
  }

  /**
   * Der VerschiebeListener sorgt dafuer, dass die Objekte auf dem
   * Zeichenblatt verschoben werden koennen.
   */
  private class VerschiebeListener extends MouseMotionAdapter
  {
    int tempX, tempY;
    Point p;
    FigurZustand r;


    @Override
    public void mouseDragged(MouseEvent e)
    {
      if (markiertesRechteck != null)
      {
	p = e.getPoint ();
	r = markiertesRechteck;

	/*
	 * Speichere die Anfangsposition des Rechtecks, um es
	 * zurueckzusatzen, falls es beim Verschieben kollidiert.
	 * Berechne die Mausposition relativ zum Rechteck, um das
	 * Rechteck am Angriffspunkt zu Verschieben.
	 */
	if (einmal)
	{
	  altX = r.x;
	  altY = r.y;
	  tempX = p.x - markiertesRechteck.x;
	  tempY = p.y - markiertesRechteck.y;
	  einmal = false;
	}
	if ( (r != null) && eintritt)
	{
	  r.x = p.x - tempX;
	  r.y = p.y - tempY;
	}
	repaint ();
	std.setzeVeraendert (true);
	menuItem3.setEnabled (true);
      }
    }
  }

  /**
   * Der FensterListener "horcht" auf den Zustand des Fensters. Wird es
   * geschlossen, ruft er die Methode schliessen() auf.
   */
  private class FensterListener implements WindowListener
  {
    @Override
    public void windowActivated(WindowEvent arg0)
    {}


    @Override
    public void windowClosed(WindowEvent arg0)
    {}


    @Override
    public void windowClosing(WindowEvent arg0)
    {
      if (std.gibVeraendert ())
      {
	int auswahl;
	String[] optionen;
	optionen = new String[2];
	optionen[0] = lokal.gibUebersetzung ("Ja");
	optionen[1] = lokal.gibUebersetzung ("Nein");
	auswahl = JOptionPane.showOptionDialog (null,lokal
	  .gibUebersetzung ("Moechten Sie vor dem Beenden speichern?"),
	  lokal.gibUebersetzung ("Achtung!"),
	  JOptionPane.YES_NO_CANCEL_OPTION,
	  JOptionPane.QUESTION_MESSAGE, null, optionen, null);
	switch (auswahl)
	{
	  case 0:
	    speichern ();
	    schliessen ();
	    break;
	  case 1:
	    schliessen ();
	    break;
	  default:
	    ; /* tue nichts */
	}
      }
      else
      {
	schliessen ();
      }
    }


    @Override
    public void windowDeactivated(WindowEvent arg0)
    {}


    @Override
    public void windowDeiconified(WindowEvent arg0)
    {}


    @Override
    public void windowIconified(WindowEvent arg0)
    {}


    @Override
    public void windowOpened(WindowEvent arg0)
    {}

  }
}